/******************************************************************************************
文件名：loice_master_parser.h
作者：狼狼    版本：Loice    创建日期：2021.9.3
文件描述：
    头文件。
历史修改记录：
1. 2021-9-3:Loice 狼狼
创建。
2. 2022-5-11:Loice 狼狼
代码公开。
******************************************************************************************/
#ifndef LOICE_PARSER__
#define LOICE_PARSER__ // Loice主设备和从设备角色只能选择一个
//+------------------------------------------------------------------------------------------+
//|                                           头文件
//+------------------------------------------------------------------------------------------+
/*|*/#include <stdint.h>
/*|*/#include <stdbool.h>
/*|*/#include "internal_cmd.h"
/*|*/#include "loice_protocol_version_1.h"
//+------------------------------------------------------------------------------------------+
//|                                         参数宏定义
//+------------------------------------------------------------------------------------------+
//|    ----------------------------------------
//|    一个解析器实例能够管理的最大会话数量
//|    ATTENTION:当数量过大时可能导致检索效率问
//|              题。
//|    ----------------------------------------
/*|*/#define MAX_SESSION_NUM 1
//|    ----------------------------------------
//|    KAP机制开关
//|    NOTE:Loice主设备端为心跳包的发送方，从对
//|         端接收数据包超时将主动关闭会话。
//|         Loice从设备的数据以及任何有效且校验
//|         通过的数据可充当心跳包。
//|    ----------------------------------------
/*|*/  #define ENABLE_KAP
//|    ----------------------------------------
//|    KAP发送间隔时间（秒）
//|    ----------------------------------------
/*|*/#define KAP_SEND_INTERVAL 5
//|    ----------------------------------------
//|    KAP超时时间（秒）
//|    ----------------------------------------
/*|*/#define KAP_TIMEOUT 8
//|
/*|*/#define PARSER_SUCCESS                    0x00000000
//|    ----------------------------------------
//|    错误码：非法的参数
//|    ----------------------------------------
/*|*/#define PARSER_ERROR_ILLEGAL_PARAM        0x90031001
//|    ----------------------------------------
//|    错误码：申请内存错误
//|    ----------------------------------------
/*|*/#define PARSER_ERROR_MALLOC               0x90031003
//|    ----------------------------------------
//|    错误码：线程创建失败
//|    ----------------------------------------
/*|*/#define PARSER_ERROR_THREAD               0x90031004
//|    ----------------------------------------
//|    错误码：当前解析器（会话）状态不支持此操作
//|    ----------------------------------------
/*|*/#define PARSER_ERROR_UNEXPECT_STATE       0x90032001
//|    ----------------------------------------
//|    错误码：当前解析器会话列表已满
//|    ----------------------------------------
/*|*/#define PARSER_ERROR_SESSION_LIST_FULL    0x90033001
//|    ----------------------------------------
//|    错误码：当前解析器会话列表是空的
//|    ----------------------------------------
/*|*/#define PARSER_ERROR_SESSION_LIST_EMPTY   0x90033002
//|    ----------------------------------------
//|    错误码：会话已经被注册
//|    ----------------------------------------
/*|*/#define PARSER_ERROR_SESSION_REGISTERED   0x90033003
//|    ----------------------------------------
//|    错误码：协议不匹配
//|    ----------------------------------------
/*|*/#define PARSER_ERROR_PROTOCOL             0x90033004
//|    ----------------------------------------
//|    错误码：会话不存在
//|    ----------------------------------------
/*|*/#define PARSER_ERROR_SESSION_NON_EXISTENT 0x90033005
//|
//|    ----------------------------------------
//|    输出状态码：
//|    0.未退出(CONN_SUCCESS)        0x00000000
//|    2.接收异常                    0x9003E002
//|    3.连接断开或会话被主动关闭    0x9003E003
//|    101. 错误的调用参数           0x9003E101
//|    102. 会话不存在               0x9003E102
//|    103. 解析器状态异常           0x9003E103
//|    104. 会话状态异常             0x9003E104
//|    105. 解析器不支持的协议类型   0x9003E105
//|    ----------------------------------------
/*|*/#define PARSER_EXIT_STAT_RX_ERROR          0x9003E002
/*|*/#define PARSER_STAT_DISCONNECT_OR_CLOSE    0x9003E003
/*|*/#define PARSER_STAT_ILLEGAL_PARAM          0x9003E101
/*|*/#define PARSER_STAT_SESSION_NON_EXISTENT   0x9003E102
/*|*/#define PARSER_STAT_PARSER_UNEXPECT_STATE  0x9003E103
/*|*/#define PARSER_STAT_SESSION_UNEXPECT_STATE 0x9003E104
/*|*/#define PARSER_STAT_UNSUPPORT_PROTOCOL     0x9003E105
//+------------------------------------------------------------------------------------------+
//|                                          数据类型
//+------------------------------------------------------------------------------------------+
//|    ----------------------------------------
//|    用于描述解析器使用的协议版本的枚举类型
//|    ----------------------------------------
/*|*/typedef enum parser_protocol_version
/*|*/{
/*|*/    PARSER_PROTOCOL_INIT = 0,
/*|*/    PARSER_PROTOCOL_1    = 1,
/*|*/}ENUM_PARSER_PROCOTOL_VERSION;
//|
//|    ----------------------------------------
//|    用于描述解析器会话状态的枚举类型
//|    NOTE:仅内部使用
//|    ----------------------------------------
/*|*/typedef enum parser_session_state
/*|*/{
/*|*/    PARSER_SESSION_STAT_INIT = 0,
/*|*/    PARSER_SESSION_STAT_STANDBY, // 初始状态
//|      ----------------------------------------
//|      指令解析线程所处的中间状态
//|      NOTE:基于此状态对异步传来的消息做处理。
//|      ----------------------------------------
/*|*/    PARSER_SESSION_STAT_GOTHEAD1,
/*|*/    PARSER_SESSION_STAT_GOTHEAD2,
/*|*/    PARSER_SESSION_STAT_GOTHEAD3,
/*|*/    PARSER_SESSION_STAT_GOTHEAD4,
/*|*/    PARSER_SESSION_STAT_GOTHEAD5,
/*|*/    PARSER_SESSION_STAT_GOTHEAD6,
/*|*/    PARSER_SESSION_STAT_GOTHEAD7,
/*|*/    PARSER_SESSION_STAT_GOTHEAD8,
/*|*/    PARSER_SESSION_STAT_HEAD_CHECK_PASS,
//|      PARSER_SESSION_STAT_CMD_BODY_CHECK_PASS,
//|      PARSER_SESSION_STAT_MSG_ID_CHECK_PASS,
//|      PARSER_SESSION_STAT_MSG_SEQ_CHECK_PASS,
//|      PARSER_SESSION_STAT_CMD_REG_CHECK_PASS,
//|      PARSER_SESSION_STAT_CMD_VERIFY_PASS,
//|      PARSER_SESSION_STAT_CMD_ACTION_CHECK_PASS,
/*|*/    PARSER_SESSION_STAT_DATA_BODY_FIXED_DONE,
//|      PARSER_SESSION_STAT_DATA_BODY_CHECK_PASS,
//|      
//|      PARSER_SESSION_STAT_EXIT,    // 会话的处理线程因故退出，等待回收会话资源
/*|*/    PARSER_SESSION_STAT_END,     // 会话已停止处理
/*|*/}ENUM_PARSER_SESSION_STATE;
//|
//|    ----------------------------------------
//|    用于存储一个解析器会话对象必要信息的结构
//|    ----------------------------------------
/*|*/typedef struct parser_session
/*|*/{
//|      ----------------------------------------
//|      当前会话对应的连接管理分配的会话ID
//|      ----------------------------------------
/*|*/    uint32_t session_id;
//|      ----------------------------------------
//|      解析器会话状态
//|      ----------------------------------------
/*|*/    ENUM_PARSER_SESSION_STATE state;
//|      ----------------------------------------
//|      本地设备号
//|      NOTE:协议版本1中，设备号仅使用24字节，后
//|           4字节保留为00H。
//|      ----------------------------------------
/*|*/    uint8_t local_device_id[28];
//|      ----------------------------------------
//|      用于内部转发的管道写端描述符
//|      ----------------------------------------
/*|*/    int internal_pipe_write;
//|
//|      ----------------------------------------
//|      用于存储当前接收的消息首部的结构体
//|      ----------------------------------------
/*|*/    ST_LOICE_PROTO_VER_1_HEAD msg_head;
//|      ----------------------------------------
//|      用于存储当前接收的消息数据体的结构体
//|      ----------------------------------------
/*|*/    ST_LOICE_PROTO_VER_1_BODY_MSG data_body;
//|      ----------------------------------------
//|      用于指示当前消息是否需要回应的标志位
//|      ----------------------------------------
/*|*/    bool flag_current_reply;
//|      ----------------------------------------
//|      用于指示下一次待接收长度的变量
//|      ----------------------------------------
/*|*/    uint32_t next_recv_len;
//|      ----------------------------------------
//|      指向当前正在接收的数据体存储内存
//|      ----------------------------------------
/*|*/    uint8_t *pdata_body;
//|      ----------------------------------------
//|      最后一次KAP的时间
//|      NOTE:用于KAP超时判断。
//|      ----------------------------------------
/*|*/    struct timeval last_kap_time;
//|      ----------------------------------------
//|      回调函数集
//|      NOTE:以下函数指针在初始化套接字对象时被
//|           赋值。
//|      ATTENTION:使用解析器对象成员函数指针前必
//|                须先对其进行初始化！
//|      ----------------------------------------
/*|*/    int (*send_data_reply)(uint32_t session_id, const uint8_t *pdata, uint32_t data_len);
/*|*/}ST_PARSER_SESSION;
//|
//|    ----------------------------------------
//|    用于描述解析器状态的枚举类型
//|    NOTE:仅内部使用
//|    ----------------------------------------
/*|*/typedef enum parser_state
/*|*/{
/*|*/    PARSER_STAT_INIT = 0,
/*|*/    PARSER_STAT_OK,
/*|*/    PARSER_STAT_TEMP,
/*|*/}ENUM_PARSER_STATE;
//|
//|    ----------------------------------------
//|    用于存储一个解析器对象必要信息的结构
//|    ----------------------------------------
/*|*/typedef struct parser
/*|*/{
//|      ----------------------------------------
//|      解析器状态
//|      ----------------------------------------
/*|*/    ENUM_PARSER_STATE state;
//|      ----------------------------------------
//|      当前解析器实例使用的协议版本
//|      ----------------------------------------
/*|*/    ENUM_PARSER_PROCOTOL_VERSION protocol_version;
//|      ----------------------------------------
//|      内部数据体转发处理线程
//|      ----------------------------------------
/*|*/    pthread_t tid;
//|      ----------------------------------------
//|      解析器内部处理线程运行许可
//|      ----------------------------------------
/*|*/    bool flag_run;
//|      ----------------------------------------
//|      本地设备号
//|      NOTE:协议版本1中，设备号仅使用24字节，后
//|           4字节保留为00H。
//|      ----------------------------------------
/*|*/    uint8_t local_device_id[28];
//|      ----------------------------------------
//|      解析器内部数据体转发通道
//|      NOTE:解析器会话收到一帧完整的数据体后，
//|           将通过该管道将结构体以无符号字节流
//|           的形式发送给数据转发处理线程。
//|      ----------------------------------------
/*|*/    int internal_pipe[2];
//|      ----------------------------------------
//|      会话列表
//|      ----------------------------------------
/*|*/    ST_PARSER_SESSION *session_list[MAX_SESSION_NUM];
//|      ----------------------------------------
//|      会话列表中存储的会话数量
//|      ----------------------------------------
/*|*/    uint32_t session_num;
//|      ----------------------------------------
//|      解析器操作互斥锁
//|      ----------------------------------------
/*|*/    pthread_mutex_t mutex;
//|      ----------------------------------------
//|      回调函数集
//|      NOTE:以下函数指针在初始化套接字对象时被
//|           赋值。
//|      ATTENTION:使用解析器对象成员函数指针前必
//|                须先对其进行初始化！
//|      ----------------------------------------
/*|*/    int (*add_session)    (struct parser * const parser_obj, uint32_t session_id);
/*|*/    int (*delete_session) (struct parser * const parser_obj, uint32_t session_id);
/*|*/    int (*cmd_trans)      (struct parser * const parser_obj, const ST_INTERNAL_CMD *pinternal_cmd,
                                                                  uint32_t args_len,
                                                                  uint8_t **ppmsg,
                                                                  uint32_t *pmsg_len,
                                                                  bool need_reply);
/*|*/    int (*parser_function)(struct parser * const parser_obj, uint32_t session_id, int sock);
/*|*/    int (*send_data_reply)(uint32_t session_id, const uint8_t *pdata, uint32_t data_len);
/*|*/    void (*kap_timeout_handle)(uint32_t session_id);
/*|*/}ST_PARSER;
//+------------------------------------------------------------------------------------------+

#ifdef __cplusplus
extern "C" {
#endif
//+------------------------------------------------------------------------------------------+
//|                                       函数/变量声明
//+------------------------------------------------------------------------------------------+
/*|*/int parser_create (ST_PARSER **ppparser_obj, ENUM_PARSER_PROCOTOL_VERSION version,
                                                  const uint8_t *plocal_device_id,
                                                  int (*send_data_reply)(uint32_t session_id, const uint8_t *pdata, uint32_t data_len),
                                                  void (*kap_timeout_handle)(uint32_t session_id));
/*|*/int parser_destroy(ST_PARSER **ppparser_obj);
//+------------------------------------------------------------------------------------------+
#ifdef __cplusplus
}
#endif /* End of __cplusplus*/

#endif /* End of #define LOICE_PARSER__ */
